#!/usr/bin/env perl

use strict;
use warnings;
use Image::Magick;

if ( $#ARGV < 2 ) {
    die "\nscdtile2img <palfile>:[pb]<offset> <tilefile>:[tb]<offset>:<count> <bmpwidth>\n\n";
}

my $paletteInfo = shift @ARGV;
my $tileInfo = shift @ARGV;
my $width = shift @ARGV;

my $magicPink = 0;

my $paletteData = &ReadPalette($paletteInfo);

my $tileData = &ReadTile($tileInfo);
my $tileDataLength = length($tileData);

my $height = $tileDataLength*2/$width;

my $status;

#my $pal = Image::Magick->new( "format"=>"png8" );
#$pal->Set('size'=>"1x16");
#$status = $pal->Read(filename => 'xc:white');
#warn "$status" if $status;

#my $img = Image::Magick->new( "format"=>"png8" );
#$img->Set('type'=>'Palette');
#$img->Set('depth'=>4);
#$img->Set('matte'=>1);
##$img->Set('alpha'=>'On');
##$img->Set('colorspace'=>'Transparent');
#$img->Set('size'=>"${width}x${height}");
#$status = $img->Read(filename => 'xc:white');
#warn "$status" if $status;

my @colormaps;
my @colors;
my @alphas;
my @indexes;

for ( my $pIndex = 0; $pIndex < 16; $pIndex++ ) {
    my $pValue0;
    my $pValue1;
    my $alpha;
    if ( $magicPink && $pIndex == 0 ) {
	$pValue0 = 0x0E;
	$pValue1 = 0x0E;
	$alpha = 1;
    } else {
	$pValue0 = ord(substr($paletteData,$pIndex*2,1));
	$pValue1 = ord(substr($paletteData,$pIndex*2+1,1));
	$alpha = 0;
    }
    my $r = &Convert3BitColorTo8BitColor($pValue1 >> 1);
    my $g = &Convert3BitColorTo8BitColor($pValue1 >> 5);
    my $b = &Convert3BitColorTo8BitColor($pValue0 >> 1);
    my $colormap = "rgba($r,$g,$b,$alpha)";
    #my $colormap = "rgb($r,$g,$b)";
    $colormaps[$pIndex] = $colormap;
    $colors[$pIndex]->[0] = $r/255;
    $colors[$pIndex]->[1] = $g/255;
    $colors[$pIndex]->[2] = $b/255;
    $alphas[$pIndex]->[0] = $alpha;
    $indexes[$pIndex]->[0] = $pIndex;
    #$img->Set('colormap[$pIndex]'=>$colormap);

    $pal->SetPixel('channel'=>'RGB','color'=>$colors[$pIndex],'x'=>0,'y'=>$pIndex);
}

##$img->Transparent('color'=>'white');

##$img->Quantize('colors'=>16,'global_colormap'=>1);
##$img->Set('colors'=>16);

##$img->Map('image'=>$pal,'dither'=>0);
#$img->Remap('image'=>$pal,'dither'=>0);

for ( my $pIndex = 0; $pIndex < 16; $pIndex++ ) {
    $img->Set('colormap[$pIndex]'=>$colormaps[$pIndex]);
}

for ( my $y = 0; $y < $height; $y++ ) {
    for ( my $x = 0; $x < $width; $x += 2 ) {
	my $tileX = int( $x / 8 );
	my $value = ord(substr($tileData,($tileX*$height+$y)*4+($x%8)/2,1));
	my $valueHi = ( $value >> 4 ) & 0x0F;
	my $valueLo = ( $value      ) & 0x0F;
	my $x1 = $x + 1;
	##$img->SetPixel('channel'=>'RGB','color'=>$colors[$valueHi],'x'=>$x,'y'=>$y);
	##$img->SetPixel('channel'=>'Alpha','color'=>$alphas[$valueHi],'x'=>$x,'y'=>$y);
	##$img->SetPixel('channel'=>'RGB','color'=>$colors[$valueLo],'x'=>$x1,'y'=>$y);
	##$img->SetPixel('channel'=>'Alpha','color'=>$alphas[$valueLo],'x'=>$x1,'y'=>$y);
	##$img->SetPixel('channel'=>'Index','color'=>$indexes[$valueHi],'x'=>$x,'y'=>$y);
	##$img->SetPixel('channel'=>'Index','color'=>$indexes[$valueLo],'x'=>$x1,'y'=>$y);
	#$img->Set("index[${x},${y}]"=>$valueHi);
	#$img->Set("index[${x1},${y}]"=>$valueLo);
    }
}

#$img->Map('image'=>$pal,'dither'=>0);

#$status = $pal->Write('png:TMPPAL.PNG');
#warn "$status" if $status;

#$status = $img->Write('png:TMP.PNG');
#warn "$status" if $status;



sub ReadPalette {
    my ($paletteInfo) = @_;
    my $paletteType = 'p';
    my $paletteOffset = 0;
    if ( $paletteInfo !~ m/^([^:]+):([pb])([0-9]+)$/ &&
	 $paletteInfo !~ m/^([^:]+)$/ ) {
	die "Bad palette info: $paletteInfo";
    }
    my $paletteFile = $1;
    if ( defined $2 ) {
	$paletteType = $2;
    }
    if ( defined $3 ) {
	$paletteOffset = $3;
    }
    if ( $paletteType eq 'p' ) {
	$paletteOffset *= 32;
    }
    if ( ! -e $paletteFile ) {
	die "Bad palette file: $paletteFile";
    }
    if ( $paletteFile =~ m/\.asm$/i ) {
	my $paletteAsmFile = $paletteFile;
	$paletteFile = 'TMP.BIN';
	system("scdasm $paletteAsmFile $paletteFile");
	if ( ! -e $paletteFile ) {
	    die "Bad scdasm since didn't make: $paletteFile";
	}
    }

    my $paletteData = chr(0x00)x32;

    open( PALETTE, $paletteFile ) or die "Cannot read palette file: $!\n";
    binmode PALETTE;
    seek(PALETTE,$paletteOffset,0);
    my $paletteDataBuffer;
    if ( read(PALETTE,$paletteDataBuffer,32) == 32 ) {
	$paletteData = $paletteDataBuffer;
    }
    close PALETTE;

    return $paletteData;
}

sub ReadTile {
    my ($tileInfo) = @_;
    if ( $tileInfo !~ m/^([^:]+):([tb])([0-9]+):([0-9]+)$/ ) {
	die "Bad tile info: $tileInfo";
    }
    my $tileFile = $1;
    my $tileType = $2;
    my $tileOffset = $3;
    my $tileCount = $4;
    if ( $tileType eq 't' ) {
	$tileOffset *= 32;
    }
    if ( ! -e $tileFile ) {
	die "Bad tile file: $tileFile";
    }
    if ( $tileFile =~ m/\.asm$/i ) {
	my $tileAsmFile = $tileFile;
	$tileFile = 'TMP.BIN';
	system("scdasm $tileAsmFile $tileFile");
	if ( ! -e $tileFile ) {
	    die "Bad scdasm since didn't make: $tileFile";
	}
    }

    my $tileData = chr(0x00)x(32*$tileCount);

    open( TILE, $tileFile ) or die "Cannot read tile file: $!\n";
    binmode TILE;
    seek(TILE,$tileOffset,0);
    my $tileDataBuffer;
    if ( read(TILE,$tileDataBuffer,(32*$tileCount)) == (32*$tileCount) ) {
	$tileData = $tileDataBuffer;
    }
    close TILE;

    return $tileData;
}

sub Convert3BitColorTo8BitColor {
    my ($bit3) = @_;
    return int( ( $bit3 & 0x07 ) * 0xFF / 0x07 + 0.5 );
}

sub Convert8BitColorTo3BitColor {
    my ($bit8) = @_;
    return int( ( $bit8 & 0xFF ) * 0x07 / 0xFF + 0.5 );
}

